﻿using System.Collections.Generic;
using System.Reflection;

namespace Kyoh.Lib.Component.Arguments
{
    /// <summary>解析済みの引数を扱うクラスを定義します。</summary>
    /// <typeparam name="T">引数オブジェクトの型を指定します。</typeparam>
    public class ParsedArguments<T>
        where T : class
    {
        private readonly T argumentsObject;
        private readonly List<string> remainingArguments;
        private readonly Dictionary<PropertyInfo, object> processors;

        /// <summary><see cref="ParsedArguments{T}"/> クラスの新しいインスタンスを初期化します。</summary>
        /// <param name="ret">解析済の引数オブジェクトを指定します。</param>
        internal ParsedArguments(T ret)
        {
            this.argumentsObject = ret;
            this.processors = new Dictionary<PropertyInfo, object>();
            this.remainingArguments = new List<string>();
        }

        /// <summary>解析結果を追加します。</summary>
        /// <param name="property">解析結果を設定する対象のプロパティの情報を設定します。</param>
        /// <param name="value">解析結果値を設定します。</param>
        internal void AddProcessor(PropertyInfo property, object value)
        {
            processors.Add(property, value);
        }

        /// <summary>解析できなかった引数を追加します。</summary>
        /// <param name="arg">引数を指定します。</param>
        internal void AddRemaining(string arg)
        {
            this.remainingArguments.Add(arg);
        }

        /// <summary>解析済の引数を用いて、新しい <typeparamref name="T"/> クラスのオブジェクトに対してプロパティを設定します。</summary>
        /// <param name="obj">引数を設定する <typeparamref name="T"/> クラスのオブジェクトを指定します。</param>
        public void Process(T obj)
        {
            foreach (var kv in processors)
                kv.Key.SetValue(obj, kv.Value, null);
        }

        /// <summary>解析できずに残った引数を取得します。</summary>
        public IList<string> Remained { get { return this.remainingArguments.AsReadOnly(); } }
    }
}
